package edu.jhu.tcj.purfuit;

import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;


public class Question {

	private int ID;
	
	private Category category;
	
	private String question;
	
	private String correctAnswer;
	
	private String[] incorrectAnswers;
	
	public Question(){ 
		
	}

	public Category getCategory() {
		return this.category;
	}
	
	public String getQuestion() {
		return question;
	}
	
	public String getCorrectAnswer() {
		return correctAnswer;
	}
	
	public String[] getIncorrectAnswersForQues() {
		Set<String> answers = new HashSet<String>();
		while (answers.size() < 3) {
			answers.add( this.incorrectAnswers[(int)Math.floor(Math.random()*this.incorrectAnswers.length)] );
		}
		return answers.toArray(new String[3]);
	}
	
	//http://java.sun.com/webservices/reference/tutorials/jaxp/html/dom.html
	public static Question[] loadQuestion(File file) throws QuestionException {
		Document doc;
		try {
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			doc = db.parse(file);
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
			throw new QuestionException("Unable to load question" + file, e);
		} catch (SAXException e) {
			e.printStackTrace();
			throw new QuestionException("Unable to load question " + file, e);
		} catch (IOException e) {
			e.printStackTrace();
			throw new QuestionException("Unable to load question" + file, e);
		}
		
		//get the root element
		Element docEle = doc.getDocumentElement();
		
		NodeList nl = docEle.getElementsByTagName("question");
		
		Question[] questions = new Question[nl.getLength()];
		if(nl != null && nl.getLength() > 0) {
			for(int i = 0 ; i < nl.getLength();i++) {
				//get the question element
				Element el = (Element)nl.item(i);

				//get the Question object
				questions[i] = new Question(el);
			}
		}
		return questions;
	}
	
	private Question(Element questionElement) {
		String title = getTextValue(questionElement,"title");
		ID = getIntValue(questionElement,"ID");
		int categoryID = getIntValue(questionElement,"category");
		category = CategoryManager.getInstance().getCategory(categoryID);
		question = getTextValue(questionElement, "text");
		correctAnswer = getTextValue(questionElement,"correct");
		incorrectAnswers = getTextValues(questionElement,"incorrect");
	}
	
	/**
	 * I take a xml element and the tag name, look for the tag and get
	 * the text content
	 * i.e for <employee><name>John</name></employee> xml snippet if
	 * the Element points to employee node and tagName is 'name' I will return John
	 */
	private String getTextValue(Element ele, String tagName) {
		String textVal = null;
		NodeList nl = ele.getElementsByTagName(tagName);
		if(nl != null && nl.getLength() > 0) {
			Element el = (Element)nl.item(0);
			textVal = el.getFirstChild().getNodeValue();
		}

		return textVal;
	}
	
	/**
	 * I take a xml element and the tag name, look for the tag and get
	 * the text content
	 * i.e for <employee><name>John</name></employee> xml snippet if
	 * the Element points to employee node and tagName is 'name' I will return John
	 */
	private String[] getTextValues(Element ele, String tagName) {
		
		NodeList nl = ele.getElementsByTagName(tagName);
		String[] textVals = new String[nl.getLength()];
		if(nl != null && nl.getLength() > 0) {
			for (int i = 0; i < nl.getLength(); i++) {
				Element el = (Element)nl.item(i);
				textVals[i] = el.getFirstChild().getNodeValue();
			}
		}
		return textVals;
	}
	
	/**
	 * Calls getTextValue and returns a int value
	 */
	private int getIntValue(Element ele, String tagName) {
		//in production application you would catch the exception
		return Integer.parseInt(getTextValue(ele,tagName));
	}
	
	public void saveQuestion() {
		//TODO Save question to XML file
	}

	/**
	 * @return the iD
	 */
	public int getID() {
		return ID;
	}

	/**
	 * @param iD the iD to set
	 */
	public void setID(int iD) {
		ID = iD;
	}

	/**
	 * @param category the category to set
	 */
	public void setCategory(Category category) {
		this.category = category;
	}

	/**
	 * @param question the question to set
	 */
	public void setQuestion(String question) {
		this.question = question;
	}

	/**
	 * @param correctAnswer the correctAnswer to set
	 */
	public void setCorrectAnswer(String correctAnswer) {
		this.correctAnswer = correctAnswer;
	}

	/**
	 * @param incorrectAnswers the incorrectAnswers to set
	 */
	public void setIncorrectAnswers(String[] incorrectAnswers) {
		this.incorrectAnswers = incorrectAnswers;
	}

	/**
	 * @return the incorrectAnswers
	 */
	public String[] getIncorrectAnswers() {
		return incorrectAnswers;
	}

	public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, QuestionException {
		Question.loadQuestion(new File("trunk/trivialpurfuit/conf/Questions/Question1.xml"));
	}
}
